前端进阶之旅前端进阶之旅
基础篇
进阶篇
高频篇
精选篇
手写篇
面经篇
AI 篇
原理篇
每日一题
小程序题库
知识卡片
  • 场景篇按分类整理的大前端场景考点
  • 历年面经按年份追踪真实考点
  • 算法题库NEW在线编码即时判题
  • 专项自测100 题快速查漏
  • 前端基础
    • HTTP从报文一路讲到 HTTPS
    • 浏览器渲染、事件循环、进程
    • 计算机基础Linux、网络、操作系统
  • 进阶专项
    • 设计模式23 种模式怎么用
    • 前端系统进阶学习大型项目工程化
    • 前端综合文章长期沉淀的实践文
  • 工程与工具
    • Node学习指南从环境搭建到服务端
    • NPM工作流script、依赖与发布
    • Docker容器化部署上手
    • Canvas图形与动画实战
  • 路线与导图
    • 思维导图知识点全景图
    • 学习路线按图索骥不跑偏
  • 动态
    • 公众号动态公众号历史文章
    • 博客动态站长的技术博客
    • 开发者导航常用工具与文档站
  • AI 助手随时提问,即时解析
  • AI 模拟面试模拟真实面试 + 报告
  • AI 知识地图串起全站知识点
  • AI 定制路线按你的简历现排
AI 热点
旧版
基础篇
进阶篇
高频篇
精选篇
手写篇
面经篇
AI 篇
原理篇
每日一题
小程序题库
知识卡片
  • 场景篇按分类整理的大前端场景考点
  • 历年面经按年份追踪真实考点
  • 算法题库NEW在线编码即时判题
  • 专项自测100 题快速查漏
  • 前端基础
    • HTTP从报文一路讲到 HTTPS
    • 浏览器渲染、事件循环、进程
    • 计算机基础Linux、网络、操作系统
  • 进阶专项
    • 设计模式23 种模式怎么用
    • 前端系统进阶学习大型项目工程化
    • 前端综合文章长期沉淀的实践文
  • 工程与工具
    • Node学习指南从环境搭建到服务端
    • NPM工作流script、依赖与发布
    • Docker容器化部署上手
    • Canvas图形与动画实战
  • 路线与导图
    • 思维导图知识点全景图
    • 学习路线按图索骥不跑偏
  • 动态
    • 公众号动态公众号历史文章
    • 博客动态站长的技术博客
    • 开发者导航常用工具与文档站
  • AI 助手随时提问,即时解析
  • AI 模拟面试模拟真实面试 + 报告
  • AI 知识地图串起全站知识点
  • AI 定制路线按你的简历现排
AI 热点
旧版
  • 基础篇

    • 环境搭建
    • node部署
    • 基础应用
  • 内置模块

    • 1.0 本地路径处理 path
    • 2.0 文件系统操作 fs
    • 3.1 基础调试 console
    • 3.2 本地调试远程服务器上的Node代码
    • 4.1 网络服务 http
    • 4.2 网络服务 http res
    • 4.3 网络服务 http req
    • 4.4 网络服务 http server
    • 4.5 网络服务 http client
    • 4.6 网络服务 https
    • 4.7 网络TCP net
    • 4.8 网络UDP dgram
    • 4.9 域名解析 dns
    • 5.0 网络地址解析 url
    • 5.1 URL查询字符串 querystring
    • 6.1 流操作 stream
    • 6.2 逐行读取 readline
    • 7.1 进程相关 process
    • 7.2 子进程 child
    • 8.1 二进制数据 buffer
    • 8.2 二进制解码 string_decoder
    • 9.1 事件机制 events
    • 9.2 实用工具模块 util
    • 9.3 数据加密 crypto
    • 9.4 MD5入门介绍及crypto模块的应用
    • 9.4 资源压缩 zlib
    • 9.5 集群 cluster
    • 9.6 v8
  • 进阶篇

    • 5分钟入门非对称加密用法
    • cluster
    • cookie_parser深入
    • crypto模块之理论篇
    • express+cookie_parser签名机制深入剖析
    • express+session实现简易身份认证
    • https
    • log4js入门实例
    • node8_napi
    • 使用 async 控制并发
    • 使用 eventproxy 控制并发
    • 使用 superagent 与 cheerio 完成简单爬虫
    • 基于express+muter的文件上传
    • 将图片转成datauri嵌入到html
    • 常用中间件 body_parser 实现解析
    • 日志模块morgan
    • 服务端字符编解码&乱码处理 charset_enc_dec
    • 测试用例mocha,should,istanbul
    • 调试日志打印debug模块
  • Express

    • 1.1 Express概览篇
    • 1.2 Express
  • Koa2

    • 1.0 koa2概览篇
    • 1.1 快速开始
    • 1.2 async await使用
    • 1.3 koa2简析结构
    • 1.4 koa中间件开发与使用
    • 10.1 单元测试
    • 11.1 开发debug
    • 12.1 快速启动
    • 12.2 框架设计
    • 12.3 分层操作
    • 12.4 数据库设计
    • 12.5 路由设计
    • 12.6 webpack4环境搭建
    • 12.7 使用react
    • 12.8 登录注册功能实现
    • 12.9 session登录态判断处理
    • 13.1 import export使用
    • 2.1 原生koa2实现路由
    • 2.2 koa router中间
    • 3.1 GET请求数据获取
    • 3.2 POST请求数据获取
    • 3.3 koa bodyparser中间件
    • 4.1 原生koa2实现静态资源服务器
    • 4.2 koa static中间件
    • 5.1 koa2使用cookie
    • 5.2 koa2实现session
    • 6.1 koa2加载模板引擎
    • 6.2 ejs模板引擎
    • 7.1 busboy模块
    • 7.2 上传文件简单实现
    • 7.3 异步上传图片实现
    • 8.1 mysql模块
    • 8.2 async await封装使用mysql
    • 8.3 项目建表初始化
    • 9.1 原生koa2实现JSONP
    • 9.2 koa jsonp中间件
  • 其他

    • 操作数据库
    • Session 与 Token
    • Cookie、Session、Token、JWT
    • Socket

# koa-static中间件使用

30 秒速记

  • 一行搞定:app.use(koaStatic(path.join(__dirname, 'static'))),内部用 koa-send 发文件
  • root 只指向专门放公开资源的目录,别指向项目根,不然源码和 .env 都能被下载
  • 只处理 GET 和 HEAD;找不到文件会 await next() 交给后面的中间件
  • 常用配置:maxage 缓存时长、immutable、index 默认首页、hidden 是否允许隐藏文件(默认不允许)、defer 是否让路由先处理
  • 目录穿越 koa-send 已经拦了,不用自己再写

koa-static 就是把上一节手写的静态服务器封装成了中间件,一行代码就能托管一个目录。 它内部用 koa-send 发文件,流式输出、Content-Type、Last-Modified、目录穿越防护都处理了。用的时候要注意两件事:root 一定要指向专门的公开目录,指向项目根就等于把源码和配置文件都放出去了;文件找不到时它不会返回 404,而是交给后面的中间件,所以后面如果有个兜底返回 hello world,缺失的图片也会拿到 200 和这段文字。

理解「koa-static中间件使用」时,要先明确输入、运行阶段和可观察输出。这里的交互实验会分别执行正常路径与失败路径,并把 Node.js 的关键状态变化和同屏代码对应起来;不能只记命令名称。

工程中还要验证退出码、资源清理和异常输入。属于 middleware 场景的配置应保持最小可复现,并在开发环境与 CI 中使用相同命令复跑,避免把平台差异或隐式默认值带到线上。

面试官追问

追问 1请求 /missing.png 也返回了 hello world,是 koa-static 出问题了吗?
参考回答

不是,这是它的设计。找不到文件就 await next(),后面的兜底中间件给了 body,状态码就是 200。兜底中间件要区分路径,静态资源找不到应该返回 404。

追问 2root 传 './static' 和 path.join(__dirname, 'static') 有区别吗?
参考回答

有。相对路径按 process.cwd() 解析,从别的目录启动就找错地方;__dirname 是当前文件所在目录,在哪启动都一样。线上统一用绝对路径。

追问 3前端打包出来的带哈希的文件,缓存怎么配?
参考回答

koaStatic(root, { maxage: 365 * 24 * 3600 * 1000, immutable: true }),maxage 单位是毫秒。index.html 不带哈希,要单独让它不缓存或短缓存,不然发版后用户拿不到新页面。

追问 4想让 /api 路由优先、静态文件兜底,怎么配?
参考回答

把 koa-static 注册在路由后面,或者传 defer: true,让它先 await next(),后面没人设置响应时再去找文件。默认是先找文件,接口路径和文件同名时文件会赢。

追问 5线上要不要让 Koa 自己托管所有静态资源?
参考回答

小项目、内部工具这样很省事。流量大的站点我会把静态资源放到 CDN 或 Nginx,Node 进程只管接口,发版、缓存、带宽都更好控制。

# koa-static中间件使用

# 使用例子

30 秒速记

  • koa-static(root, opts):root 用 path.join(__dirname, 'static') 锚定成绝对路径,别依赖启动目录
  • 只处理 GET / HEAD;找到文件就直接响应,找不到才 await next() 交给后面的中间件
  • 常用选项:maxage(毫秒)、index(默认 index.html)、hidden(默认不发点文件)、gzip / br(发预压缩文件)、defer
  • root 只放公开资源,别指向项目根目录,否则 package.json、源码都能被直接下载
  • const static = ... 在严格模式和 ESM 里会报错,变量名换成 serve

koa-static 就是一个「先去目录里找文件,找到就返回,找不到就放行」的中间件。 示例里它挂在最前面,访问 /index.html、/js/index.js 能直接拿到文件;访问一个不存在的路径,它找不到就 next(),请求落到后面那个写 hello world 的中间件。所以看到 hello world 不代表文件存在,反而说明静态目录没命中。目录我一定用 __dirname 拼绝对路径,因为相对路径是相对进程启动目录算的,换个目录 node xxx/index.js 就全挂。上线时我还会给带内容 hash 的资源配长 maxage,或者干脆把静态资源交给 Nginx / CDN。

demo源码

https://github.com/poetries/daily-code-practice/tree/master/node/koa/koa2-demo/static-use-middleware/

const Koa = require('koa')
const path = require('path')
const static = require('koa-static')

const app = new Koa()

// 静态资源目录对于相对入口文件index.js的路径
const staticPath = './static'

app.use(static(
  path.join( __dirname,  staticPath)
))

app.use( async ( ctx ) => {
  ctx.body = 'hello world'
})

app.listen(3000, () => {
  console.log('[demo] static-use-middleware is starting at port 3000')
})

@前端进阶之旅: 代码已经复制到剪贴板

面试官追问

追问 1同事把 './static' 直接传给 koa-static,在项目根目录启动没问题,用 pm2 从别的目录启动就 404 了,为什么?
参考回答

相对路径是按 process.cwd() 解析的,不是按 index.js 所在目录。启动目录一变,./static 指向的就是另一个地方。用 path.join(__dirname, 'static') 锚定到文件位置就稳了。

追问 2访问一个不存在的 /missing.png,返回的是 200 和 hello world,这算正常吗?
参考回答

对这段代码来说是预期行为:koa-static 没找到文件就放行,后面的中间件无条件写了 body,Koa 自动给 200。真实项目里兜底中间件要按路径判断,图片、脚本这种资源请求找不到就该老老实实返回 404,不然前端排查会被误导。

追问 3想让业务路由优先,静态文件兜底,怎么配?
参考回答

两种办法:把 koa-static 挪到路由后面,或者保留原位置但开 defer: true。defer 的意思是先 await next() 跑完后面的中间件,只有响应还是空的(404)时才去读文件。

追问 4有人请求 /../package.json,能把项目配置下载走吗?
参考回答

koa-static 底层用的 koa-send 会把路径限制在 root 里,路径穿越会被拦掉。真正的风险是 root 本身配错,比如直接指向项目根目录,那 package.json 和源码都能直接访问,hidden 只挡得住 .env 这类点文件。

追问 5静态资源每次都重新下载,怎么让浏览器缓存?
参考回答

加 maxage,单位是毫秒,比如 serve(dir, { maxage: 365 * 24 * 3600 * 1000 })。前提是文件名带内容 hash,不然发版后用户拿到的还是旧文件;index.html 这种入口文件要单独设短缓存或不缓存。

# 效果

# 访问 http://localhost:3000

# 访问 http://localhost:3000/index.html

# 访问 http://localhost:3000/js/index.js

基础篇
进阶篇
高频篇
精选篇
手写篇
面经篇
AI 篇
原理篇
每日一题
小程序题库
知识卡片
  • 场景篇按分类整理的大前端场景考点
  • 历年面经按年份追踪真实考点
  • 算法题库NEW在线编码即时判题
  • 专项自测100 题快速查漏
  • 前端基础
    • HTTP从报文一路讲到 HTTPS
    • 浏览器渲染、事件循环、进程
    • 计算机基础Linux、网络、操作系统
  • 进阶专项
    • 设计模式23 种模式怎么用
    • 前端系统进阶学习大型项目工程化
    • 前端综合文章长期沉淀的实践文
  • 工程与工具
    • Node学习指南从环境搭建到服务端
    • NPM工作流script、依赖与发布
    • Docker容器化部署上手
    • Canvas图形与动画实战
  • 路线与导图
    • 思维导图知识点全景图
    • 学习路线按图索骥不跑偏
  • 动态
    • 公众号动态公众号历史文章
    • 博客动态站长的技术博客
    • 开发者导航常用工具与文档站
  • AI 助手随时提问,即时解析
  • AI 模拟面试模拟真实面试 + 报告
  • AI 知识地图串起全站知识点
  • AI 定制路线按你的简历现排
AI 热点
旧版
  • 基础篇

    • 环境搭建
    • node部署
    • 基础应用
  • 内置模块

    • 1.0 本地路径处理 path
    • 2.0 文件系统操作 fs
    • 3.1 基础调试 console
    • 3.2 本地调试远程服务器上的Node代码
    • 4.1 网络服务 http
    • 4.2 网络服务 http res
    • 4.3 网络服务 http req
    • 4.4 网络服务 http server
    • 4.5 网络服务 http client
    • 4.6 网络服务 https
    • 4.7 网络TCP net
    • 4.8 网络UDP dgram
    • 4.9 域名解析 dns
    • 5.0 网络地址解析 url
    • 5.1 URL查询字符串 querystring
    • 6.1 流操作 stream
    • 6.2 逐行读取 readline
    • 7.1 进程相关 process
    • 7.2 子进程 child
    • 8.1 二进制数据 buffer
    • 8.2 二进制解码 string_decoder
    • 9.1 事件机制 events
    • 9.2 实用工具模块 util
    • 9.3 数据加密 crypto
    • 9.4 MD5入门介绍及crypto模块的应用
    • 9.4 资源压缩 zlib
    • 9.5 集群 cluster
    • 9.6 v8
  • 进阶篇

    • 5分钟入门非对称加密用法
    • cluster
    • cookie_parser深入
    • crypto模块之理论篇
    • express+cookie_parser签名机制深入剖析
    • express+session实现简易身份认证
    • https
    • log4js入门实例
    • node8_napi
    • 使用 async 控制并发
    • 使用 eventproxy 控制并发
    • 使用 superagent 与 cheerio 完成简单爬虫
    • 基于express+muter的文件上传
    • 将图片转成datauri嵌入到html
    • 常用中间件 body_parser 实现解析
    • 日志模块morgan
    • 服务端字符编解码&乱码处理 charset_enc_dec
    • 测试用例mocha,should,istanbul
    • 调试日志打印debug模块
  • Express

    • 1.1 Express概览篇
    • 1.2 Express
  • Koa2

    • 1.0 koa2概览篇
    • 1.1 快速开始
    • 1.2 async await使用
    • 1.3 koa2简析结构
    • 1.4 koa中间件开发与使用
    • 10.1 单元测试
    • 11.1 开发debug
    • 12.1 快速启动
    • 12.2 框架设计
    • 12.3 分层操作
    • 12.4 数据库设计
    • 12.5 路由设计
    • 12.6 webpack4环境搭建
    • 12.7 使用react
    • 12.8 登录注册功能实现
    • 12.9 session登录态判断处理
    • 13.1 import export使用
    • 2.1 原生koa2实现路由
    • 2.2 koa router中间
    • 3.1 GET请求数据获取
    • 3.2 POST请求数据获取
    • 3.3 koa bodyparser中间件
    • 4.1 原生koa2实现静态资源服务器
    • 4.2 koa static中间件
    • 5.1 koa2使用cookie
    • 5.2 koa2实现session
    • 6.1 koa2加载模板引擎
    • 6.2 ejs模板引擎
    • 7.1 busboy模块
    • 7.2 上传文件简单实现
    • 7.3 异步上传图片实现
    • 8.1 mysql模块
    • 8.2 async await封装使用mysql
    • 8.3 项目建表初始化
    • 9.1 原生koa2实现JSONP
    • 9.2 koa jsonp中间件
  • 其他

    • 操作数据库
    • Session 与 Token
    • Cookie、Session、Token、JWT
    • Socket
完整面试题地址:
作者:程序员poetry
扫码关注作者公众号:「前端进阶之旅」 每天分享技术干货
前端进阶之旅公众号二维码

koa-static中间件使用|Nodejs专题系列

# koa-static中间件使用

30 秒速记

  • 一行搞定:app.use(koaStatic(path.join(__dirname, 'static'))),内部用 koa-send 发文件
  • root 只指向专门放公开资源的目录,别指向项目根,不然源码和 .env 都能被下载
  • 只处理 GET 和 HEAD;找不到文件会 await next() 交给后面的中间件
  • 常用配置:maxage 缓存时长、immutable、index 默认首页、hidden 是否允许隐藏文件(默认不允许)、defer 是否让路由先处理
  • 目录穿越 koa-send 已经拦了,不用自己再写

koa-static 就是把上一节手写的静态服务器封装成了中间件,一行代码就能托管一个目录。 它内部用 koa-send 发文件,流式输出、Content-Type、Last-Modified、目录穿越防护都处理了。用的时候要注意两件事:root 一定要指向专门的公开目录,指向项目根就等于把源码和配置文件都放出去了;文件找不到时它不会返回 404,而是交给后面的中间件,所以后面如果有个兜底返回 hello world,缺失的图片也会拿到 200 和这段文字。

理解「koa-static中间件使用」时,要先明确输入、运行阶段和可观察输出。这里的交互实验会分别执行正常路径与失败路径,并把 Node.js 的关键状态变化和同屏代码对应起来;不能只记命令名称。

工程中还要验证退出码、资源清理和异常输入。属于 middleware 场景的配置应保持最小可复现,并在开发环境与 CI 中使用相同命令复跑,避免把平台差异或隐式默认值带到线上。

面试官追问

追问 1请求 /missing.png 也返回了 hello world,是 koa-static 出问题了吗?
参考回答

不是,这是它的设计。找不到文件就 await next(),后面的兜底中间件给了 body,状态码就是 200。兜底中间件要区分路径,静态资源找不到应该返回 404。

追问 2root 传 './static' 和 path.join(__dirname, 'static') 有区别吗?
参考回答

有。相对路径按 process.cwd() 解析,从别的目录启动就找错地方;__dirname 是当前文件所在目录,在哪启动都一样。线上统一用绝对路径。

追问 3前端打包出来的带哈希的文件,缓存怎么配?
参考回答

koaStatic(root, { maxage: 365 * 24 * 3600 * 1000, immutable: true }),maxage 单位是毫秒。index.html 不带哈希,要单独让它不缓存或短缓存,不然发版后用户拿不到新页面。

追问 4想让 /api 路由优先、静态文件兜底,怎么配?
参考回答

把 koa-static 注册在路由后面,或者传 defer: true,让它先 await next(),后面没人设置响应时再去找文件。默认是先找文件,接口路径和文件同名时文件会赢。

追问 5线上要不要让 Koa 自己托管所有静态资源?
参考回答

小项目、内部工具这样很省事。流量大的站点我会把静态资源放到 CDN 或 Nginx,Node 进程只管接口,发版、缓存、带宽都更好控制。

# koa-static中间件使用

# 使用例子

30 秒速记

  • koa-static(root, opts):root 用 path.join(__dirname, 'static') 锚定成绝对路径,别依赖启动目录
  • 只处理 GET / HEAD;找到文件就直接响应,找不到才 await next() 交给后面的中间件
  • 常用选项:maxage(毫秒)、index(默认 index.html)、hidden(默认不发点文件)、gzip / br(发预压缩文件)、defer
  • root 只放公开资源,别指向项目根目录,否则 package.json、源码都能被直接下载
  • const static = ... 在严格模式和 ESM 里会报错,变量名换成 serve

koa-static 就是一个「先去目录里找文件,找到就返回,找不到就放行」的中间件。 示例里它挂在最前面,访问 /index.html、/js/index.js 能直接拿到文件;访问一个不存在的路径,它找不到就 next(),请求落到后面那个写 hello world 的中间件。所以看到 hello world 不代表文件存在,反而说明静态目录没命中。目录我一定用 __dirname 拼绝对路径,因为相对路径是相对进程启动目录算的,换个目录 node xxx/index.js 就全挂。上线时我还会给带内容 hash 的资源配长 maxage,或者干脆把静态资源交给 Nginx / CDN。

demo源码

https://github.com/poetries/daily-code-practice/tree/master/node/koa/koa2-demo/static-use-middleware/

const Koa = require('koa')
const path = require('path')
const static = require('koa-static')

const app = new Koa()

// 静态资源目录对于相对入口文件index.js的路径
const staticPath = './static'

app.use(static(
  path.join( __dirname,  staticPath)
))

app.use( async ( ctx ) => {
  ctx.body = 'hello world'
})

app.listen(3000, () => {
  console.log('[demo] static-use-middleware is starting at port 3000')
})

@前端进阶之旅: 代码已经复制到剪贴板

面试官追问

追问 1同事把 './static' 直接传给 koa-static,在项目根目录启动没问题,用 pm2 从别的目录启动就 404 了,为什么?
参考回答

相对路径是按 process.cwd() 解析的,不是按 index.js 所在目录。启动目录一变,./static 指向的就是另一个地方。用 path.join(__dirname, 'static') 锚定到文件位置就稳了。

追问 2访问一个不存在的 /missing.png,返回的是 200 和 hello world,这算正常吗?
参考回答

对这段代码来说是预期行为:koa-static 没找到文件就放行,后面的中间件无条件写了 body,Koa 自动给 200。真实项目里兜底中间件要按路径判断,图片、脚本这种资源请求找不到就该老老实实返回 404,不然前端排查会被误导。

追问 3想让业务路由优先,静态文件兜底,怎么配?
参考回答

两种办法:把 koa-static 挪到路由后面,或者保留原位置但开 defer: true。defer 的意思是先 await next() 跑完后面的中间件,只有响应还是空的(404)时才去读文件。

追问 4有人请求 /../package.json,能把项目配置下载走吗?
参考回答

koa-static 底层用的 koa-send 会把路径限制在 root 里,路径穿越会被拦掉。真正的风险是 root 本身配错,比如直接指向项目根目录,那 package.json 和源码都能直接访问,hidden 只挡得住 .env 这类点文件。

追问 5静态资源每次都重新下载,怎么让浏览器缓存?
参考回答

加 maxage,单位是毫秒,比如 serve(dir, { maxage: 365 * 24 * 3600 * 1000 })。前提是文件名带内容 hash,不然发版后用户拿到的还是旧文件;index.html 这种入口文件要单独设短缓存或不缓存。

# 效果

# 访问 http://localhost:3000

# 访问 http://localhost:3000/index.html

# 访问 http://localhost:3000/js/index.js

← 4.1 原生koa2实现静态资源服务器5.1 koa2使用cookie →

fe